// interpretor
package main

import (
	"fmt"
	"math"
	"math/rand"
	"os"
	"strconv"
	//"strings"
)

//***************************************************************
type returnType int

const (
	returnType_COMMON   returnType = 0
	returnType_BREAK    returnType = 1
	returnType_CONTINUE returnType = 2
	returnType_RETURN   returnType = 3
)

type Interpreter struct {
	startModule *DrModule
	Functions   map[string]*DrFunction
	callStack   CallStack
	BasicFuncs  map[string]FuncIndex
	listClass   *DrClass
	tupleClass  *DrClass
	TrueObject  *DrBoolean
	FalseObject *DrBoolean
	NoneObject  *DrAbstractObject
	locals      map[string]IObject
	Value       interface{}
	PrintSet    map[IObject]int
}

func (this *Interpreter) hasPrinted(ob IObject) bool {
	_, ok := this.PrintSet[ob]
	if !ok {
		return false
	} else {
		return true
	}
}
func (this *Interpreter) NewModule() *DrModule {
	mod := new(DrModule)
	mod.Type = TypeModule
	mod.members = make(map[string]IObject)
	return mod

}

func (this *Interpreter) NewFuncCall(func0 *DrFunction) *DrFuncCall {
	call := new(DrFuncCall)
	call.Type = TypeCall
	call.Name = func0.Name
	call.function = func0
	call.locals = make(map[string]IObject)

	return call
}
func IsNumber(s string) bool {
	// for _, x := range s {
	// 	if !((x >= '0' && x <= '9') || x == '.') {
	// 		return false
	// 	}
	// }
	// return true
	_, ok := strconv.ParseFloat(s, 64)
	if ok != nil {
		return false
	}
	return true
}

/* func addNum (x,y) {
z=12.0
xx=cos(x)
yy=sin(y)
result=xx+yy+z
}*/

func (this *Interpreter) FindFunction(funcName string, funcCall *DrFuncCall, realParams []IObject) (*DrFunction, IObject) {
	//先要找出当前实际调用的方法对象
	var func0 *DrFunction
	var ob IObject
	if funcName[0] == '.' { //属于对象成员函数，或模块成员函数
		members := realParams[0].getMembers()
		funcObj := members[funcName[1:]]
		if funcObj == nil {
			panic("the method is not existed")
		}
		if funcObj.getType() == TypeBuiltInFunc {
			ob = funcObj.executeMethod(funcName[1:], realParams) //只处理了内建的，用户定义的需要以下面的方式处理
			//panic("出问题了这地方")
			return nil, ob
		} else if funcObj.getType() == TypeUserFunc { //如果是用户定义的函数，则获取func0用于下面的运行
			func0 = funcObj.(*DrFunction)
			//funcCall.module = realParams[0].(*DrModule)
			//realParams = realParams[1:] //第一个参数是所属对象，所以把剩余的参数作为真参数
		}
	} else {

		funcOb := funcCall.module.getMembers()[funcName]
		if funcOb == nil {
			funcOb = funcCall.locals[funcName]
		}
		if funcOb != nil {
			func0 = funcOb.(*DrFunction)
		} else {

			func0 = this.Functions[funcName] //属于系统内建函数
		}
	}
	return func0, ob
}

func (this *Interpreter) CallFunction(funcCall *DrFuncCall, realParams []IObject, oldClausIndex int) IObject {
	//先要找出当前实际调用的方法对象

	func0 := funcCall.function
	oldIndex := this.callStack.Len()
	//把实参的值拷贝到局部变量空间中
	for i, para := range func0.ParamNames {
		funcCall.locals[para] = realParams[i]
		//fmt.Println(funcCall.funcName, i, "Locals:", para)
	}
	//获取函数体中的所有clause
	funcCall.localClauses = func0.Clauses

	//执行所有子句
	n := len(funcCall.localClauses)
	var lastValue IObject
	//处理函数中每一条子句
	//fmt.Println("处理函数", funcCall.funcName, "中每一条子句", "参数包括：", funcCall.ParaNames[0], funcCall.ParaNames[1])
	for i_clauses := 0; i_clauses < n; i_clauses++ {
		//fmt.Println("第", i_clauses, "条子句", "共", n, "条")
		clause := funcCall.localClauses[i_clauses]

		//fmt.Println("当前子句为", clause)
		lastValue, _ = this.ExecuteGenerateClause(clause, funcCall, oldIndex)
	}
	//fmt.Println(funcCall.funcName, "最终执行结果是", lastValue.AsString())
	funcCall.returnObject = lastValue
	return lastValue
}

func (this *Interpreter) Eval(sysfunc FuncIndex, params []IObject) IObject {
	switch sysfunc {
	case SysFunc_add: //+
		{
			if len(params) < 1 || params[0] == nil {
				panic("abcde")
			}
			if params[0].getType() == TypeString || params[1].getType() == TypeString {
				return NewStr(params[0].AsString() + params[1].AsString())
			}
			if params[0].getType() == TypeNum || params[0].getType() == TypeInt {
				return NewNum(params[0].getDouble() + params[1].getDouble())
			} else if params[0].getType() == TypeList {
				return NewList(append(params[0].(*DrList).GetElems(), params[1].(*DrList).GetElems()...))
			} else if params[0].getType() == TypeTuple {
				return NewTuple(append(params[0].(*DrTuple).GetElems(), params[1].(*DrTuple).GetElems()...))
			} else if params[0].getType() == TypeNumArray {
				if params[1].getType() == TypeNumArray {
					return params[0].(*DrNumArray).AddNum2d(params[1].(*DrNumArray))
				}
				if params[1].getType() == TypeNum || params[1].getType() == TypeInt {
					return params[0].(*DrNumArray).Add(params[1].getDouble())
				}
			} else {
				panic("not implemented here")
			}
		}
	case SysFunc_sub:
		{
			para := params[0]
			if para.getType() == TypeNum || para.getType() == TypeInt {
				if params[1].getType() == TypeNumArray {
					return params[1].(*DrNumArray).Add(-para.getDouble())
				} else {
					return NewNum(para.getDouble() - params[1].getDouble())
				}
			}

			if para.getType() == TypeNumArray {
				if params[1].getType() == TypeNumArray {
					value := params[1].(*DrNumArray)
					return para.(*DrNumArray).AddNum2d(value.Multiply(-1))

				} else if params[1].getType() == TypeNum || params[1].getType() == TypeInt {
					value := params[1].getDouble()
					return para.(*DrNumArray).Multiply(-value)
				}
			}
		}
	case SysFunc_addset:
		{
			if params[0].getType() == TypeInt && params[1].getType() == TypeInt {
				return NewInt(params[0].getInt() + params[1].getInt())
			} else {
				return NewNum(params[0].getDouble() + params[1].getDouble())
			}

		}
	case SysFunc_assign: //=
		{
			return params[0]
		}
	case SysFunc_cos:
		{ //cos

			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				val := para.getDouble()
				return NewNum(math.Cos(val))
			} else if para.getType() == TypeNumArray {
				return para.(*DrNumArray).Cos()
			}

		}
	case SysFunc_sin:
		{ //sin
			para := params[0]
			if para.getType() == TypeNum {
				val := params[0].getDouble()
				return NewNum(math.Sin(val))
			} else if para.getType() == TypeInt {
				val := params[0].(*DrInt).AsFloat()
				return NewNum(math.Sin(val))
			} else if para.getType() == TypeNumArray {
				return para.(*DrNumArray).Sin()
			}
		}
	case SysFunc_exp:
		{ //cos
			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				val := para.getDouble()
				return NewNum(math.Exp(val))
			} else if para.getType() == TypeNumArray {
				return para.(*DrNumArray).Exp()
			}

		}
	case SysFunc_log:
		{ //cos
			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				val := para.getDouble()
				return NewNum(math.Log(val))
			} else if para.getType() == TypeNumArray {
				return para.(*DrNumArray).Log()
			}

		}
	case SysFunc_tan:
		{
			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				val := para.getDouble()
				return NewNum(math.Tan(val))
			} else if para.getType() == TypeNumArray {
				return para.(*DrNumArray).Atan()
			}
		}
	case SysFunc_atan:
		{
			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				val := params[0].getDouble()
				return NewNum(math.Atan(val))
			} else if para.getType() == TypeNumArray {
				return para.(*DrNumArray).Atan()
			}
		}
	case SysFunc_abs:
		{
			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				val := params[0].getDouble()
				return NewNum(math.Abs(val))
			} else if para.getType() == TypeNumArray {
				return para.(*DrNumArray).Abs()
			}
		}
	case SysFunc_sign:
		{
			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				val := params[0].getDouble()
				if val > 0 {
					return NewNum(1)
				} else if val < 0 {
					return NewNum(-1)
				} else {
					return NewNum(0)
				}
			} else if para.getType() == TypeNumArray {
				panic("not implemented")
			}

		}
	case SysFunc_mul:
		{
			para := params[0]
			if para.getType() == TypeNum || para.getType() == TypeInt {
				if params[1].getType() == TypeNumArray {
					return params[1].(*DrNumArray).Multiply(para.getDouble())
				} else {
					return NewNum(para.getDouble() * params[1].getDouble())
				}
			}
			if para.getType() == TypeList {
				list := para.(*DrList)
				n := params[1].getInt()
				result := list
				for i := 0; i < n-1; i++ {
					result = result.AddList(list).(*DrList)
				}
				return result
			}
			if para.getType() == TypeNumArray && params[1].getType() == TypeNumArray {
				value := params[1].(*DrNumArray)
				return para.(*DrNumArray).MultiNum2d(value)
			} else if params[1].getType() == TypeNum || params[1].getType() == TypeInt {
				value := params[1].getDouble()
				return para.(*DrNumArray).Multiply(value)
			}

		}
	case SysFunc_div:
		{
			para := params[0]
			if para.getType() == TypeNum || para.getType() == TypeInt {
				if params[1].getType() == TypeNumArray {
					return params[1].(*DrNumArray).Reciprocal(para.getDouble())
				} else {
					return NewNum(para.getDouble() / params[1].getDouble())
				}
			}

			if para.getType() == TypeNumArray && params[1].getType() == TypeNumArray {
				value := params[1].(*DrNumArray)
				return para.(*DrNumArray).MultiNum2d(value.Reciprocal(1.0))

			} else if params[1].getType() == TypeNum || params[1].getType() == TypeInt {
				value := params[1].getDouble()
				return para.(*DrNumArray).Multiply(1.0 / value)
			}
		}
	case SysFunc_pow:
		{
			para := params[0]
			if para.getType() == TypeInt || para.getType() == TypeNum {
				v1 := para.getDouble()
				v2 := params[1].getDouble()
				return NewNum(math.Pow(v1, v2))
			} else if para.getType() == TypeNumArray && (params[1].getType() == TypeNum || params[1].getType() == TypeInt) {
				return para.(*DrNumArray).Pow(params[1].getDouble())
			}
			panic("not implemented")
		}

	case SysFunc_print:
		{
			this.PrintSet = make(map[IObject]int)
			for i := 0; i < len(params); i++ {
				if params[i] == nil {
					fmt.Print("None ")
				} else {
					params[i].Print(this)
				}
			}
			fmt.Println()
			return nil
		}

	case SysFunc_list:
		{
			return CreateListFromParam(params)
			//return NewList(params)
		}
	case SysFunc_tuple:
		{
			return NewTuple(params)
		}
	case SysFunc_larger:
		{
			if params[0].getType() != params[1].getType() {
				panic("cannot compare objects of different types")
			}
			if params[0].getType() == TypeNum && params[0].getDouble() > params[1].getDouble() {
				return this.TrueObject
			}
			if params[0].getType() == TypeString && params[0].AsString() > params[1].AsString() {
				return this.TrueObject
			}
			if params[0].getType() == TypeInt && params[0].getInt() > params[1].getInt() {
				return this.TrueObject
			}
			return this.FalseObject
		}
	case SysFunc_largEqu:
		{
			if params[0].getType() != params[1].getType() {
				panic("cannot compare objects of different types")
			}
			if params[0].getType() == TypeNum && params[0].getDouble() >= params[1].getDouble() {
				return this.TrueObject
			}
			if params[0].getType() == TypeString && params[0].AsString() >= params[1].AsString() {
				return this.TrueObject
			}

			if params[0].getType() == TypeInt && params[0].getInt() >= params[1].getInt() {
				return this.TrueObject
			}
			return this.FalseObject
		}
	case SysFunc_smaller:
		{
			if params[0].getType() != params[1].getType() {
				panic("cannot compare objects of different types")
			}
			if params[0].getType() == TypeNum && params[0].getDouble() < params[1].getDouble() {
				return this.TrueObject
			}
			if params[0].getType() == TypeString && params[0].AsString() < params[1].AsString() {
				return this.TrueObject
			}

			if params[0].getType() == TypeInt && params[0].getInt() < params[1].getInt() {
				return this.TrueObject
			}
			return this.FalseObject
		}
	case SysFunc_smalEqu:
		{
			if params[0].getType() != params[1].getType() {
				panic("cannot compare objects of different types")
			}
			if params[0].getType() == TypeNum && params[0].getDouble() <= params[1].getDouble() {
				return this.TrueObject
			}

			if params[0].getType() == TypeString && params[0].AsString() <= params[1].AsString() {
				return this.TrueObject
			}

			if params[0].getType() == TypeInt && params[0].getInt() <= params[1].getInt() {
				return this.TrueObject
			}
			return this.FalseObject
			panic("comparison is not implemented for this type")
		}
	case SysFunc_equal:
		{

			if params[0].getType() != params[1].getType() {
				panic("cannot compare objects of different types")
			}

			if params[0] == params[1] {
				return this.TrueObject
			}

			if params[0].getType() == TypeBool && params[0] == params[1] {
				return this.TrueObject
			}
			fmt.Println("come here", params[0].getType())
			if params[0].getType() == TypeNum && params[0].getDouble() == params[1].getDouble() {
				return this.TrueObject
			}
			if params[0].getType() == TypeInt && params[0].getInt() == params[1].getInt() {
				return this.TrueObject
			}
			if params[0].getType() == TypeString && params[0].AsString() == params[1].AsString() {
				return this.TrueObject
			}
			return this.FalseObject
			panic("not implemented")
		}
	case SysFunc_notEqu:
		{
			if params[0].getType() != params[1].getType() {
				panic("cannot compare objects of different types")
			}
			if params[0].getType() == TypeObject || params[1].getType() == TypeObject {
				if params[0].(*DrAbstractObject) != params[1].(*DrAbstractObject) {
					return this.TrueObject
				} else {
					return this.FalseObject
				}
			}
			if params[0].getType() == TypeBool && params[0] != params[1] {
				return this.TrueObject
			}

			if params[0].getType() == TypeNum && params[0].getDouble() != params[1].getDouble() {
				return this.TrueObject
			}

			if params[0].getType() == TypeInt && params[0].getInt() != params[1].getInt() {
				return this.TrueObject
			}

			if params[0].getType() == TypeString && params[0].AsString() != params[1].AsString() {
				return this.TrueObject
			}
			return this.FalseObject

			panic("comparison is not implemented for this type")
		}
	case SysFunc_range:
		{
			if len(params) == 1 {
				n := params[0].getInt()
				return NewRange(0, n, 1)

			} else if len(params) == 2 {
				start := params[0].getInt()
				end := params[1].getInt()
				return NewRange(start, end, 1)
			} else if len(params) == 3 {
				start := params[0].getInt()
				end := params[1].getInt()
				step := params[2].getInt()
				return NewRange(start, end, step)
			}
		}
	case SysFunc_arange:
		{
			if len(params) == 1 {
				n := params[0].getInt()
				arr := NewNumArray1d(n)
				for i := 0; i < n; i++ {
					arr.data[i] = float64(i)
				}
				return arr

			} else if len(params) == 2 {
				start := params[0].getInt()
				end := params[1].getInt()
				n := end - start
				arr := NewNumArray1d(n)
				for i := 0; i < n; i++ {
					arr.data[i] = float64(start + i)
				}
				return arr
			} else if len(params) == 3 {
				start := params[0].getInt()
				end := params[1].getInt()
				step := params[2].getInt()
				values := make([]float64, 0, (end-start)/step)
				for {
					values = append(values, float64(start))
					start += step
					if start >= end {
						break
					}
				}
				n := len(values)
				arr := NewNumArray1d(n)
				arr.data = values
				return arr
			}
		}
	case SysFunc_getItem:
		{
			type0 := params[0].getType()
			switch type0 {
			case TypeList:
				{
					para0 := params[0].(*DrList)
					obj := params[1]
					if obj.getType() == TypePair {
						obP := obj.(*DrPair)
						start := obP.elem_A.getInt()
						if start < 0 {
							start += para0.Len()
						}
						end := 0
						if obP.elem_B == nil {
							end = para0.Len()
						} else {
							end = obP.elem_B.getInt()
							if end < 0 {
								end += para0.Len()
							}
						}

						return NewList(para0.GetElems()[start:end])
					} else if obj.getType() == TypeTuple {
						//专门用于多维下标的处理时才用，比如二维数组
						panic("not implemented now")
					} else { //只有一个索引
						index := params[1].getInt()
						if index < 0 {
							index += para0.Len()
						}
						return para0.GetElems()[index]
					}
				}
			case TypeNumArray:
				{
					numArr := params[0].(*DrNumArray)
					return numArr.GetItems(params[1:])
				}
			case TypeStringArray:
				{
					obj := params[1]
					if obj.getType() == TypePair { //范围切割
						arr0 := params[0].(*DrStrArray)
						obP := obj.(*DrPair)
						start := obP.elem_A.getInt()
						if start < 0 {
							start += arr0.Len()
						}
						end := obP.elem_B.getInt()

						if end < 0 {
							end += arr0.Len()
						}
						elems := arr0.strlist[start:end]

						arr := NewStrArray(1, end-start)
						copy(arr.strlist, elems)
						return arr
					} else if obj.getType() == TypeInt || obj.getType() == TypeNum {
						arr0 := params[0].(*DrStrArray)
						index := params[1].getInt()
						if index < 0 {
							index += arr0.Len()
						}
						return NewStr(arr0.strlist[index])
					}
				}
			case TypeTuple:
				{
					para0 := params[0].(*DrTuple)
					obj := params[1]
					if obj.getType() == TypePair {
						obP := obj.(*DrPair)
						start := obP.elem_A.getInt()
						if start < 0 {
							start += para0.Len()
						}
						end := 0
						if obP.elem_B == nil {
							end = para0.Len()
						} else {
							end = obP.elem_B.getInt()
							if end < 0 {
								end += para0.Len()
							}
						}
						return NewTuple(para0.GetElems()[start:end])
					} else if obj.getType() == TypeTuple {
						//专门用于多维下标的处理时才用，比如二维数组
						panic("not implemented now")
					} else {
						index := params[1].getInt()
						if index < 0 {
							index += para0.Len()
						}
						return para0.GetElems()[index]
					}
				}
			case TypeMap:
				{
					map0 := params[0].(*DrMap)
					return map0.GetValue(params[1])
				}
			}
			panic("not implemented this this type")
		}
	case SysFunc_setItem:
		{
			para0 := params[0]
			switch para0.getType() {
			case TypeList:
				{
					obj := params[1]
					if obj.getType() == TypePair || obj.getType() == TypeTuple {
						panic("not implemented for other types, now only support list type")
					}
					index := obj.getDouble()
					para0.(*DrList).GetElems()[int(index)] = params[2]
					return nil
				}
			case TypeNumArray:
				{
					arr := para0.(*DrNumArray)
					arr.SetItems(params[1], params[2])
					return nil

				} //end CaseNumArray
			case TypeMap:
				{
					map0 := params[0].(*DrMap)
					map0.SetKeyValue(params[1], params[2])
					return nil
				}
			}
		}
	case SysFunc_pair:
		{
			n := len(params)
			if n != 2 {
				panic("incorrect number of parameters " + string(n))
			}
			return NewPair(params[0], params[1])
		}
	case SysFunc_return:
		{
			n := len(params)
			if n > 1 {
				return NewTuple(params)
			} else {
				return params[0]
			}
		}
	case SysFunc_dir:
		{
			n := len(params)
			if n > 1 {
				panic("incorrect number of parameters " + string(n))
			}
			if n == 0 {
				list := make([]IObject, 0, 100)

				for key, _ := range this.BasicFuncs {
					list = append(list, NewStr(key))
				}
				for key, _ := range this.locals {
					list = append(list, NewStr(key))
				}
				for key, _ := range this.Functions {
					list = append(list, NewStr(key))
				}
				for key, _ := range this.startModule.members {
					list = append(list, NewStr(key))
				}
				listob := NewList(list)
				return listob
			} else if n == 1 {
				list := make([]IObject, 0, 100)

				for key, _ := range params[0].getMembers() {
					list = append(list, NewStr(key))
				}
				listob := NewList(list)
				return listob
			}

		}
	case SysFunc_and:
		{
			var a bool
			if params[0] == this.FalseObject || params[0] == this.NoneObject {
				a = false
			} else {
				a = true
			}
			var b bool
			if params[1] == this.FalseObject || params[1] == this.NoneObject {
				b = false
			} else {
				b = true
			}
			if a && b == true {
				return this.TrueObject
			} else {
				return this.FalseObject
			}
		}
	case SysFunc_or:
		{
			var a bool
			if params[0] == this.FalseObject || params[0] == this.NoneObject {
				a = false
			} else {
				a = true
			}
			var b bool
			if params[1] == this.FalseObject || params[1] == this.NoneObject {
				b = false
			} else {
				b = true
			}
			if a || b == true {
				return this.TrueObject
			} else {
				return this.FalseObject
			}
		}
	case SysFunc_not:
		{
			if params[0] == this.FalseObject {
				return this.TrueObject
			} else {
				return this.FalseObject
			}
		}
	case SysFunc_array:
		{
			return CreateArrayFromParam(params)
		}
	case SysFunc_file:
		{
			ob := NewTxtReader(params[0].(*DrString).AsString())

			ob.members = make(map[string]IObject)
			ob.members["readlines"] = NewFunction("readlines", nil)
			ob.members["toNumArray"] = NewFunction("toNumArray", nil)
			return ob
		}
	case SysFunc_random:
		{
			n := len(params)
			if n == 0 {
				return NewNum(rand.Float64())
			} else if n == 1 {
				arr := NewNumArray2d(1, params[0].getInt())
				for i, _ := range arr.data {
					arr.data[i] = rand.Float64()
				}
				return arr
			} else if n == 2 {
				arr := NewNumArray2d(params[0].getInt(), params[1].getInt())
				for i, _ := range arr.data {
					arr.data[i] = rand.Float64()
				}
				return arr
			}
		}

	case SysFunc_map:
		{
			Map := this.NewMap()
			for _, each := range params {
				pair, ok := each.(*DrPair)
				if !ok {
					panic("parameters must be pair")
				}
				Map.SetKeyValue(pair.elem_A, pair.elem_B)
			}
			return Map
		}

	case SysFunc_ones:
		{
			if len(params) > 1 {
				rows := params[0].getInt()
				cols := params[1].getInt()
				num := NewNumArray2d(rows, cols)
				for i, _ := range num.data {
					num.data[i] = 1.0
				}
				return num
			}
			if len(params) == 1 {
				cols := params[0].getInt()
				num := NewNumArray2d(1, cols)
				for i, _ := range num.data {
					num.data[i] = 1.0
				}
				return num
			}
		}
	case SysFunc_int:
		{
			return NewInt(params[0].getInt())
		}
	case SysFunc_float:
		{
			return NewNum(params[0].getDouble())
		}
	case SysFunc_str:
		{
			return NewStr(params[0].AsString())
		}

	case SysFunc_len:
		{
			obj, ok := params[0].(ISequence)
			if ok {
				return NewInt(obj.Len())
			} else {
				panic("only sequence object has metod len")
			}

		}
	}
	fmt.Println(sysfunc)
	panic("not implemented:")
	return nil
}
func (self *Interpreter) Init() {
	self.listClass = new(DrClass)
	self.listClass.Type = TypeClass
	self.listClass.members = make(map[string]IObject)
	self.listClass.className = "list"

	self.listClass.members["append"] = NewFunction("append", []string{"obj"})
	self.listClass.members["pop"] = NewFunction("pop", []string{"obj"})

	self.TrueObject = NewBoolen(true)

	self.FalseObject = NewBoolen(false)

	self.NoneObject = new(DrAbstractObject)
	self.NoneObject.Type = TypeObject

	if self.locals == nil {
		self.locals = make(map[string]IObject)
	}
	self.PrintSet = make(map[IObject]int)

}

//clause为当前子句, funcCall为当前子句所在的函数
func (this *Interpreter) ExecuteGenerateClause(clause *DrClause, funcCall *DrFuncCall, oldIndex int) (IObject, returnType) {
	//如果存在item和assign先后联用的clause，要修改为setItem (list, pos, elem)的clause

	if clause.funcName == "assign" && len(clause.parameters) >= 2 && clause.parameters[0].funcName == "getItem" {
		clp := clause.parameters[0]
		//fmt.Println(clp.funcName)
		clp.funcName = "setItem"
		clp.AddParameter(clause.parameters[1])
		clause = clp
	}
	switch clause.ClauseType {
	case ClauseType_SINGLE:
		{
			ob, flag := this.ExecuteSingleClause(clause, funcCall, oldIndex)
			return ob, flag
		}
	case ClauseType_IF:
		{
			ob, flag := this.ExecuteIfClause(clause, funcCall, oldIndex)
			return ob, flag
		}
	case ClauseType_FOR:
		{
			ob, flag := this.ExecuteForClause(clause, funcCall, oldIndex)
			return ob, flag
		}
	case ClauseType_WHILE:
		{
			ob, flag := this.ExecuteWhileClause(clause, funcCall, oldIndex)
			return ob, flag
		}
	case ClauseType_VAR:
		{
			if clause.funcName == "True" {
				return this.TrueObject, returnType_COMMON
			}
			if clause.funcName == "False" {
				return this.FalseObject, returnType_COMMON
			}
			if clause.funcName == "None" {
				return this.NoneObject, returnType_COMMON
			}

			_, ok := this.BasicFuncs[clause.funcName] //内建函数
			if ok {
				return NewStr("<builtin function: " + clause.funcName + " >"), returnType_COMMON
			}
			ob := funcCall.locals[clause.funcName] //局部变量
			if ob == nil {
				ob = funcCall.module.getMembers()[clause.funcName] //同模块内函数
			}
			if ob == nil {
				panic("object " + clause.funcName + " cannot be found in current space")

			}
			return ob, returnType_COMMON
		}

	case ClauseType_CONSTANT:
		{
			num, _ := strconv.ParseFloat(clause.funcName, 64)
			return NewNum(num), returnType_COMMON
		}
	}
	fmt.Println(clause.ClauseType)
	panic("not implemented" + clause.funcName + " ")
	return nil, returnType_COMMON
}

//处理If else语句的函数
func (this *Interpreter) ExecuteIfClause(clause *DrClause, funcCall *DrFuncCall, oldIndex int) (IObject, returnType) {
	//if语句的条件语句的存放与普通单语句是相同的，因此首先要执行单语句，获得返回值
	//方法是先将if语句的类型临时变为单语句，但执行完后再变回来，此种方法危险但很高效

	ob, _ := this.ExecuteSingleClause(clause.parameters[0], funcCall, oldIndex)

	//如果条件满足，则执行其包含的一系列子句
	if ob == this.TrueObject {
		for i := 0; i < len(clause.subClauseA); i++ {
			child := clause.subClauseA[i]
			if child.funcName == "break" {
				return nil, returnType_BREAK
			}
			if child.funcName == "continue" {
				return nil, returnType_CONTINUE
			}
			ob1, flag := this.ExecuteGenerateClause(child, funcCall, oldIndex)
			if flag == returnType_RETURN {
				return ob1, flag
			}
		}
	} else {
		for i := 0; i < len(clause.subClauseB); i++ {
			child := clause.subClauseB[i]
			if child.funcName == "break" {
				return nil, returnType_BREAK
			}
			if child.funcName == "continue" {
				return nil, returnType_CONTINUE
			}
			ob, flag := this.ExecuteGenerateClause(child, funcCall, oldIndex)
			if flag == returnType_RETURN {
				return ob, flag
			}
		}
	}
	return nil, 0
}
func (this *Interpreter) ExecuteForClause(clause *DrClause, funcCall *DrFuncCall, oldIndex int) (IObject, returnType) {

	//if语句的条件语句的存放与普通单语句是相同的，因此首先要执行单语句，获得返回值
	//方法是先将if语句的类型临时变为单语句，但执行完后再变回来，此种方法危险但很高效
	//clause.ClauseType = ClauseType_SINGLE
	param0 := clause.parameters[0]
	result, _ := this.ExecuteGenerateClause(param0, funcCall, oldIndex)
	ob, ok := result.(IIterable)
	if !ok {
		panic("Condition object must be sequence object")
	}

	ob.ResetCursor()

	//如果条件满足，则执行其包含的一系列子句。这里的条件只取决于前面运行的返回值
	for {
		value := ob.Next()
		if value == nil {
			break
		}
		funcCall.locals[clause.returnName] = value
		for i := 0; i < clause.GetChildSize(); i++ {
			child := clause.subClauseA[i]
			obj, flag := this.ExecuteGenerateClause(child, funcCall, oldIndex)
			iscontinue := false
			switch flag {

			case returnType_BREAK:
				{ //是break时直接退出
					return obj, flag
				}
			case returnType_CONTINUE:
				{ //是continue时
					iscontinue = true
					break
				}
			case returnType_RETURN:
				{
					return obj, flag
				}
			}
			if iscontinue {
				break
			}
		}
	}
	return nil, returnType_COMMON
}
func (this *Interpreter) ExecuteWhileClause(clause *DrClause, funcCall *DrFuncCall, oldIndex int) (IObject, returnType) {
	for {
		param0 := clause.parameters[0]
		value, _ := this.ExecuteGenerateClause(param0, funcCall, oldIndex)
		if value == nil || (value.getType() == TypeBool && value.(*DrBoolean) == this.FalseObject) {
			break
		}
		funcCall.locals[clause.returnName] = value
		for i := 0; i < clause.GetChildSize(); i++ {
			child := clause.subClauseA[i]
			obj, flag := this.ExecuteGenerateClause(child, funcCall, oldIndex)
			iscontinue := false
			switch flag {

			case returnType_BREAK:
				{ //是break时直接退出
					return obj, flag
				}
			case returnType_CONTINUE:
				{ //是continue时
					iscontinue = true
					break
				}
			case returnType_RETURN:
				{
					return obj, flag
				}
			}
			if iscontinue {
				break
			}
		}
	}
	return nil, returnType_COMMON
}

func (this *Interpreter) ExecuteSingleClause(clause *DrClause, funcCall *DrFuncCall, oldIndex int) (IObject, returnType) {
	//准备好所有调用当前clause中函数所需的参数
	npar := len(clause.parameters)
	realParams := make([]IObject, 0, npar)

	//逐个准备实参
	for j := 0; j < npar; j++ {
		param := clause.parameters[j]

		if param == nil {
			realParams = append(realParams, nil)
			continue
		}
		if param.ClauseType == ClauseType_CONSTANT {
			if param.Type == TypeNum { //如果prame是数字，则直接转化为num
				v_int, err := strconv.ParseInt(param.funcName, 10, 64)
				if err == nil {
					realParams = append(realParams, NewInt(int(v_int)))
				} else {
					value, _ := strconv.ParseFloat(param.funcName, 64)
					realParams = append(realParams, NewNum(value))
				}
			} else if param.Type == TypeString {
				realParams = append(realParams, NewStr(param.funcName))
			} else {
				panic("not implemented here")
			}
			//fmt.Println("Direct get a value:", value)
		} else if param.ClauseType == ClauseType_VAR {
			if clause.funcName == "assign" && j == 0 {
				realParams = append(realParams, nil)
				//fmt.Println("A set function appeared")
			} else if param.funcName == "import" {
				realParams = append(realParams, nil)
			} else if param.funcName == "False" || param.funcName == "false" {
				realParams = append(realParams, this.FalseObject)
			} else if param.funcName == "True" || param.funcName == "true" {
				realParams = append(realParams, this.TrueObject)
			} else if param.funcName == "None" || param.funcName == "none" || param.funcName == "nil" || param.funcName == "null" {
				realParams = append(realParams, this.NoneObject)
			} else if param.funcName == "ENDINDEX" {
				realParams = append(realParams, nil)
			} else {
				//realParams[j] = funcCall.locals[param.Name]
				ob := funcCall.locals[param.funcName] //如果是变量，则从局部变量中查找对象
				if ob == nil {                        //如果对象是空的，则判断是不是模块中的函数对象
					ob = funcCall.module.getMembers()[param.funcName]
				}
				if ob == nil { //如果是带点的变量名，且包含了参数，那应该是其第一参数的成员函数，或者变量
					if param.funcName[0] == '.' && len(param.parameters) == 1 {
						mod := funcCall.module.getMembers()[param.parameters[0].funcName]
						ob = mod.getMembers()[param.funcName[1:]]
					}
				}
				realParams = append(realParams, ob)
			}
		} else { ////如果是另一个子句，则处理子句
			ob, _ := this.ExecuteGenerateClause(param, funcCall, 0)
			//fmt.Println("A clause result =", ob.value())
			realParams = append(realParams, ob)
		}

	}

	//碰到return,break,continue要语句特殊处理
	if clause.funcName == "return" {
		if npar == 0 {
			return nil, returnType_RETURN
		}
		if npar == 1 {
			return realParams[0], returnType_RETURN
		}
		if npar > 1 {
			return NewTuple(realParams), returnType_RETURN
		}
	} else if clause.funcName == "break" {
		return nil, returnType_BREAK
	} else if clause.funcName == "continue" {
		return nil, returnType_CONTINUE
	}

	//如果子句中的函数是基本函数，直接求取
	sysfunc, ok := this.BasicFuncs[clause.funcName]
	if ok {
		if sysfunc == SysFunc_assign {
			param0 := clause.parameters[0]
			varName := param0.funcName
			if varName == "tuple" {
				//param1 := clause.parameters[1]
				if realParams[1].getType() != TypeTuple { //assign前后两个参数都必须是tuple才行
					panic("must be tuple")
				}
				if len(param0.parameters) > realParams[1].(*DrTuple).Len() {
					panic("must have a fewer number of parameters")
				}
				for i := 0; i < len(param0.parameters); i++ {
					name := param0.parameters[i].funcName
					funcCall.locals[name] = realParams[1].(*DrTuple).Elements[i]
				}

			} else {
				//_, ok := this.BasicFuncs[clause.parameters[1].funcName]

				funcCall.locals[varName] = realParams[1]
			}
			return nil, 0

		} else if sysfunc == SysFunc_import {
			filename := clause.parameters[0].funcName + ".drg"
			//如果能找到*.drg文件，则直接导入
			_, err := os.Stat(filename)
			if os.IsExist(err) {
				source := NewSource(filename)
				code := NewCode(source.tokens, source.module)
				module := code.ProcessModule(this)
				funcCall.module.getMembers()[code.moduleName] = module
			}
			//如果是C动态链接库
			filename = clause.parameters[0].funcName + ".so"
			_, err = os.Stat(filename)
			if os.IsExist(err) {
				dllHandle := openDLL(filename)
				module := new(DrModule)
				module.dllHandle = dllHandle
				module.isDll = true
				funcCall.module.getMembers()[clause.parameters[0].funcName] = module
			}
			return nil, 0
		} else {
			lastValue := this.Eval(sysfunc, realParams)
			if sysfunc == SysFunc_addset {
				funcCall.locals[clause.parameters[0].funcName] = lastValue
			}
			return lastValue, 0
		}
	} else { //如果不是基本函数，则生成一份FuncCall拷贝，用递归方式执行

		var ob IObject
		var func0 *DrFunction
		func0, ob = this.FindFunction(clause.funcName, funcCall, realParams)

		if func0 != nil {
			newcall := this.NewFuncCall(func0)
			newcall.module = func0.module
			if clause.funcName[0] == '.' {

				//newcall.module = realParams[0]
				realParams = realParams[1:]
			}
			// if len(realParams) == 0 {
			// 	return func0, 0
			// }

			ob = this.CallFunction(newcall, realParams, 0)
		}
		return ob, 0
	}
}
